/*
 * Copyright 2014 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package io.netty.handler.ssl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.io.pem.PemObject;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;

/** Pem utility class for loading pem files */
public final class PemCertTool {

	static {
		Security.setProperty("crypto.policy", "unlimited");
		Security.addProvider(new BouncyCastleProvider());
	}

	public static X509Certificate[] toX509Certificates(File pem) throws CertificateException, IOException {
		try (InputStream in = new FileInputStream(pem)) {
			return toX509Certificates(in);
		}
	}

	public static X509Certificate[] toX509Certificates(InputStream in) throws CertificateException {
		ByteBuf[] byteBufs = PemReader.readCertificates(in);

		List<X509Certificate> x509Certificates = new ArrayList<>();
		CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
		for (ByteBuf byteBuf : byteBufs) {
			x509Certificates
					.add((X509Certificate) certificateFactory.generateCertificate(new ByteBufInputStream(byteBuf)));
		}

		return x509Certificates.toArray(new X509Certificate[0]);
	}

	public static PrivateKey toPrivateKey(File pem)
			throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {

		try (InputStream in = new FileInputStream(pem)) {
			return toPrivateKey(in);
		}
	}

	public static PrivateKey toPrivateKey(InputStream in)
			throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {

		org.bouncycastle.util.io.pem.PemReader pemReader = new org.bouncycastle.util.io.pem.PemReader(
				new InputStreamReader(in));
		PemObject pem = pemReader.readPemObject();
		if (pem == null) {
			if (pemReader != null)
				pemReader.close();
			throw new IOException("The file does not represent a pem account.");
		}

		pemReader.close();

		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(pem.getContent());
//		KeyFactory keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);

		try {
			return KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME).generatePrivate(encodedKeySpec);
		} catch (InvalidKeySpecException ignore) {
			try {
				return KeyFactory.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME)
						.generatePrivate(encodedKeySpec);
			} catch (InvalidKeySpecException ignore2) {
				try {
					return KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME)
							.generatePrivate(encodedKeySpec);
				} catch (InvalidKeySpecException e) {
					throw new InvalidKeySpecException("Neither RSA, DSA nor EC worked", e);
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		String pemPath = "C:\\Users\\taifu\\Desktop\\4339949_www.taocisuyuan.com.pem";
		String keyPath = "C:\\Users\\taifu\\Desktop\\4339949_www.taocisuyuan.com.key";
		PrivateKey privateKey = PemCertTool.toPrivateKey(new File(keyPath));
		X509Certificate[] x509Certificates = PemCertTool.toX509Certificates(new File(pemPath));

		String pk = Hex.toHexString(privateKey.getEncoded());
		System.out.println("privateKey=" + pk);
		for (X509Certificate x509Certificate : x509Certificates) {
			System.out.println("/************************************************");
			System.out.println(x509Certificate);
			System.out.println("************************************************/");
		}
	}
}
